package cn.com.kh;

import cn.com.elite.Util;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;


import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import static cn.com.kh.KHUtil.getMD5;

/**
 * Author: Tao
 * Date:  2021/7/10
 * Description:
 */
public class signUtil {

    private static final Logger log = LoggerFactory.getLogger(signUtil.class);

    // 签名超时时长，默认时间为5分钟，ms
    private static final int SIGN_EXPIRED_TIME = 5 * 60 * 1000;

    private static final String SIGN_KEY = "sign";

    private static final String TIMESTAMP_KEY = "timestamp";

    private static final String ACCESS_KEY = "access_key";

    private static final String ACCESS_SECRET = "access_secret";

    public static JSONObject CheckSign(JSONObject callJson) {

        Map<String, Object> result = new HashMap<String, Object>();
        String timestamp = callJson.getString(TIMESTAMP_KEY);
        String accessKey = callJson.getString(ACCESS_KEY);
        String accessSecret = getProperty.get(accessKey);
        JSONObject json = null;

        if (!org.apache.commons.lang.StringUtils.isNumeric(timestamp)) {
            result.put("code", 1000);
            result.put("msg", "请求时间戳不合法");
            json = new JSONObject(result);
            return json;
        }

        // 检查KEY是否合理
        if (StringUtils.isEmpty(accessKey) || StringUtils.isEmpty(accessSecret)) {
            result.put("code", 1001);
            result.put("msg", "加密KEY不合法");
            json = new JSONObject(result);
            return json;
        }
        Long ts = Long.valueOf(timestamp);
        // 禁止超时签名
        if (System.currentTimeMillis() - ts > SIGN_EXPIRED_TIME) {
            result.put("code", 1002);
            result.put("msg", "请求超时");
            json = new JSONObject(result);
            return json;
        }

        try {
            if (!verifySign(callJson, accessKey, accessSecret)) {
                result.put("code", 1003);
                result.put("msg", "签名错误");
                json = new JSONObject(result);
                return json;
            }
        } catch (UnsupportedEncodingException e) {

            result.put("code", 1004);
            result.put("msg", "签名校验异常");

            json = new JSONObject(result);
            return json;
        }
        return json;
    }

    // 验证签名
    private static boolean verifySign(JSONObject callJson, String accessKey, String accessSecret) throws UnsupportedEncodingException {

        Map<String, Object> params = new HashMap<String, Object>();
        String originSign = callJson.getString(SIGN_KEY);
        log.debug("加密前签名:" + originSign);

        // 将报文转为Map
        params = callJson.getInnerMap();
        params.remove(SIGN_KEY);

        String sign = createSign(params, accessSecret);
        log.debug("加密后签名:" + sign);

        return sign.equals(originSign);
    }

    // 创建签名
    private static String createSign(Map<String, Object> params, String accessSecret) throws UnsupportedEncodingException {
        Set<String> keysSet = params.keySet();
        Object[] keys = keysSet.toArray();
        Arrays.sort(keys);
        StringBuilder temp = new StringBuilder();
        boolean first = true;
        for (Object key : keys) {
            if (first) {
                first = false;
            } else {
                temp.append("&");
            }
            temp.append(key).append("=");
            Object value = params.get(key);
            String valueString = "";
            if (null != value) {

                valueString = String.valueOf(value);
            }
            temp.append(valueString);
        }

        log.debug("待签名字符串:" + temp.toString());
        String signAfter = null;
        try {
            String aesString = AESUtil.aesEncrypt(temp.toString(), accessSecret);
            log.debug("AES字符串:" + aesString);
            signAfter = Util.getMD5Str(aesString).toUpperCase();
            log.debug("MD5字符串:" + signAfter);
        } catch (Exception e) {
            log.error("AES-MD5签名字符串加密异常！", e);
        }
        return signAfter;
    }

    // 获取签名
    public static String getSign(JSONObject callJson, String accessKey, String accessSecret) throws UnsupportedEncodingException {

        Map<String, Object> params = new HashMap<String, Object>();

        // 将报文转为Map
        params = callJson.getInnerMap();
        params.remove(SIGN_KEY);

        String sign = createSign(params, accessSecret);
        log.debug("加密后签名:" + sign);

        return sign;
    }
}